From c6467b5e5a4312f709d25cbeea25784374453d1c Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 13 Feb 2006 15:58:50 +0100 Subject: [PATCH] Fix HVM event handling some more. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/io.c | 26 +++++++++++++++++++++++++- xen/arch/x86/hvm/svm/svm.c | 10 +++------- xen/arch/x86/hvm/svm/vmcb.c | 8 ++++---- xen/arch/x86/hvm/vmx/io.c | 5 +++-- xen/arch/x86/hvm/vmx/vmx.c | 10 +++------- xen/include/asm-x86/hvm/io.h | 1 + 6 files changed, 39 insertions(+), 21 deletions(-) diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index 9f32792e8f..39d53cccd5 100644 --- a/xen/arch/x86/hvm/io.c +++ b/xen/arch/x86/hvm/io.c @@ -704,7 +704,6 @@ void hvm_wait_io(void) { /* Clear master flag, selector flag, event flag each in turn. */ v->vcpu_info->evtchn_upcall_pending = 0; - smp_mb__before_clear_bit(); clear_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel); smp_mb__after_clear_bit(); if ( test_and_clear_bit(port, &d->shared_info->evtchn_pending[0]) ) @@ -727,6 +726,31 @@ void hvm_wait_io(void) v->vcpu_info->evtchn_upcall_pending = 1; } +void hvm_safe_block(void) +{ + struct vcpu *v = current; + struct domain *d = v->domain; + int port = iopacket_port(d); + + for ( ; ; ) + { + /* Clear master flag & selector flag so we will wake from block. */ + v->vcpu_info->evtchn_upcall_pending = 0; + clear_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel); + smp_mb__after_clear_bit(); + + /* Event pending already? */ + if ( test_bit(port, &d->shared_info->evtchn_pending[0]) ) + break; + + do_sched_op(SCHEDOP_block, 0); + } + + /* Reflect pending event in selector and master flags. */ + set_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel); + v->vcpu_info->evtchn_upcall_pending = 1; +} + /* * Local variables: * mode: C diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index b7bccf9b99..1c83f4a79a 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -1812,16 +1811,14 @@ static inline void svm_vmexit_do_hlt(struct vmcb_struct *vmcb) inst_len = __get_instruction_length(vmcb, INSTR_HLT, NULL); __update_guest_eip(vmcb, inst_len); - if ( !v->vcpu_id ) { + if ( !v->vcpu_id ) next_pit = get_pit_scheduled(v, vpit); - } next_wakeup = get_apictime_scheduled(v); - if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 ) { + if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 ) next_wakeup = next_pit; - } if ( next_wakeup != - 1 ) set_timer(¤t->arch.hvm_svm.hlt_timer, next_wakeup); - do_sched_op(SCHEDOP_block, 0); + hvm_safe_block(); } @@ -2434,7 +2431,6 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs) #else svm_store_cpu_user_regs(®s, v); domain_pause_for_debugger(); - do_sched_op(SCHEDOP_yield, 0); #endif } break; diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c index 6c56e58127..5d45a4c25e 100644 --- a/xen/arch/x86/hvm/svm/vmcb.c +++ b/xen/arch/x86/hvm/svm/vmcb.c @@ -487,16 +487,16 @@ int load_vmcb(struct arch_svm_struct *arch_svm, u64 phys_hsa) */ void svm_do_resume(struct vcpu *v) { - struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit; + struct domain *d = v->domain; + struct hvm_virpit *vpit = &d->arch.hvm_domain.vpit; - if ( event_pending(v) || + if ( test_bit(iopacket_port(d), &d->shared_info->evtchn_pending[0]) || test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags) ) hvm_wait_io(); /* pick up the elapsed PIT ticks and re-enable pit_timer */ - if ( vpit->first_injected ) { + if ( vpit->first_injected ) pickup_deactive_ticks(vpit); - } svm_set_tsc_shift(v, vpit); /* We can't resume the guest if we're waiting on I/O */ diff --git a/xen/arch/x86/hvm/vmx/io.c b/xen/arch/x86/hvm/vmx/io.c index b36ceb15f6..b7a27f904a 100644 --- a/xen/arch/x86/hvm/vmx/io.c +++ b/xen/arch/x86/hvm/vmx/io.c @@ -173,11 +173,12 @@ asmlinkage void vmx_intr_assist(void) void vmx_do_resume(struct vcpu *v) { - struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); + struct domain *d = v->domain; + struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit; vmx_stts(); - if ( event_pending(v) || + if ( test_bit(iopacket_port(d), &d->shared_info->evtchn_pending[0]) || test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags) ) hvm_wait_io(); diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index fd0edf1272..05517ae291 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -1643,16 +1642,14 @@ void vmx_vmexit_do_hlt(void) struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); s_time_t next_pit=-1,next_wakeup; - if ( !v->vcpu_id ) { + if ( !v->vcpu_id ) next_pit = get_pit_scheduled(v,vpit); - } next_wakeup = get_apictime_scheduled(v); - if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 ) { + if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 ) next_wakeup = next_pit; - } if ( next_wakeup != - 1 ) set_timer(¤t->arch.hvm_vmx.hlt_timer, next_wakeup); - do_sched_op(SCHEDOP_block, 0); + hvm_safe_block(); } static inline void vmx_vmexit_do_extint(struct cpu_user_regs *regs) @@ -1849,7 +1846,6 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs) __vm_clear_bit(GUEST_PENDING_DBG_EXCEPTIONS, PENDING_DEBUG_EXC_BS); domain_pause_for_debugger(); - do_sched_op(SCHEDOP_yield, 0); break; } diff --git a/xen/include/asm-x86/hvm/io.h b/xen/include/asm-x86/hvm/io.h index db428d617f..577e966077 100644 --- a/xen/include/asm-x86/hvm/io.h +++ b/xen/include/asm-x86/hvm/io.h @@ -148,6 +148,7 @@ static inline int irq_masked(unsigned long eflags) extern void handle_mmio(unsigned long, unsigned long); extern void hvm_wait_io(void); +extern void hvm_safe_block(void); extern void hvm_io_assist(struct vcpu *v); extern void pic_irq_request(int *interrupt_request, int level); extern void hvm_pic_assist(struct vcpu *v); -- 2.30.2